package com.hanyxx.thread.lock;

import lombok.SneakyThrows;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author layman
 * @date 2021/2/9
 */
public class Demo05 {
    public static void main(String[] args) {
        Demo05Service service = new Demo05Service();
        //生产-消费(一对一关系)
        /*Demo05Producer producer = new Demo05Producer(service);
        Demo05Consumer consumer = new Demo05Consumer(service);
        producer.start();
        consumer.start();*/
        ////生产-消费(多对多关系)
        int size = 5;
        Demo05Producer[] producers = new Demo05Producer[size];
        Demo05Consumer[] consumers = new Demo05Consumer[size];

        for (int i = 0; i < size; i++) {
            char name = (char)('A'+i);
            producers[i] = new Demo05Producer(service);
            producers[i].setName("生产者"+name);
            producers[i].start();

            consumers[i] = new Demo05Consumer(service);
            consumers[i].setName("消费者"+name);
            consumers[i].start();
        }
    }
}
class Demo05Service{
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private String value = "";

    public void setValue() throws InterruptedException {
        lock.lock();
        while(!"".equals(value)){
            //如果有值，就等待消费
            System.out.println(Thread.currentThread().getName()+" 进入等待状态 ");
            condition.await();
        }
        //如果没有值，就生产值，然后通知消费者消费
        value = System.currentTimeMillis()+" - "+System.nanoTime();
        System.out.println(Thread.currentThread().getName()+" 生产的值： " + value);
        //Thread.sleep(500L);
        //condition.signal();
        //多生产者与多消费者模式需要唤醒所有等待的线程，否则会唤醒消费者，进入无限等待状态
        condition.signalAll();
        lock.unlock();
    }
    public void getValue() throws InterruptedException {
        lock.lock();
        while(!"".equals(value)){
            //如果有值，就消费，然后通知生产者生产
            System.out.println(Thread.currentThread().getName()+" 消费的值： " + value);
            value = "";
            //Thread.sleep(500L);
            //condition.signal();
            //多生产者与多消费者模式需要唤醒所有等待的线程，否则会唤醒消费者，进入无限等待状态
            condition.signalAll();
        }
        //如果没有值，就等待生产者生产值
        System.out.println(Thread.currentThread().getName()+" 进入等待状态 ");
        condition.await();
        lock.unlock();
    }
}
class Demo05Producer extends Thread{
    private Demo05Service service;

    public Demo05Producer(Demo05Service service){
        this.service = service;
    }

    @SneakyThrows
    @Override
    public void run() {
        while(true){
            service.setValue();
        }
    }
}
class Demo05Consumer extends Thread{
    private Demo05Service service;

    public Demo05Consumer(Demo05Service service){
        this.service = service;
    }

    @SneakyThrows
    @Override
    public void run() {
        while(true){
            service.getValue();
        }
    }
}
